package com.astrofizzbizz.downtimesimulator;


public class DownTimeSimulator 
{
	private int numFailures;
	private double devMTTF;
	private double devMTTR;
	private int numDevices;
	private int numDevicesOffOk;
	private double tstep;
	private Device[] device;
	private double[][] failureDistribution = null;
	private double machineMTTF = -1.0;
	private double machineMTTR = -1.0;
	private double machineAvail = 0.0;
	
	public DownTimeSimulator(int numFailures, double devMTTF, double devMTTR, int numDevices, int numDevicesOffOk, double tstep)
	{
		this.numFailures = numFailures;
		this.devMTTF = devMTTF;
		this.devMTTR = devMTTR;
		this.numDevices = numDevices;
		this.numDevicesOffOk = numDevicesOffOk;
		this.tstep = tstep;
		initializeDevices();
	}
	private void initializeDevices()
	{
		device = new Device[numDevices];
		for (int ii = 0; ii < numDevices; ++ii) device[ii] = new Device(devMTTF, devMTTR, tstep);
	}
	public void generateDistribution()
	{
		failureDistribution = new double[numFailures][2];
		initializeDevices();
		double machineUpTime = tstep;
		double machineDnTime = 0.0;
		int ifail = 0;
		System.out.println("Generating Distribution...");
		int percentComplete = 0;
		while (ifail < numFailures)
		{
			int ndevFailed = 0;
			for (int idev = 0; idev < numDevices; ++idev)
			{
				device[idev].setState();
				if (!device[idev].isOnState()) ndevFailed = ndevFailed + 1;
			}
			if (ndevFailed > numDevicesOffOk)
			{
				if (machineUpTime > 0.5 * tstep)
				{
					failureDistribution[ifail][0] = machineUpTime;
					machineUpTime = 0.0;
				}
				machineDnTime = machineDnTime + tstep;
			}
			else
			{
				if (machineUpTime < 0.5 * tstep)
				{
					failureDistribution[ifail][1] = machineDnTime;
					machineDnTime = 0.0;
					ifail = ifail + 1;
					double dpercentComplete = 100 * ((double) ifail) / ((double) numFailures);
					int newPercentComplete = (int) dpercentComplete;
					if (newPercentComplete != percentComplete)
					{
						percentComplete = newPercentComplete;
						System.out.println("Percent Complete = " + percentComplete);
					}
				}
				machineUpTime = machineUpTime + tstep;
			}
		}
		machineMTTF = 0.0;
		machineMTTR = 0.0;
		for (int ii = 0; ii < numFailures; ++ii)
		{
			machineMTTF = machineMTTF + failureDistribution[ii][0];
			machineMTTR = machineMTTR + failureDistribution[ii][1];
		}
		machineMTTF = machineMTTF / ((double) numFailures);
		machineMTTR = machineMTTR / ((double) numFailures);
		machineAvail = machineMTTF / (machineMTTF + machineMTTR);
	}
	
	public int getNumFailures() {return numFailures;}
	public double getDevMTTF() {return devMTTF;}
	public double getDevMTTR() {return devMTTR;}
	public int getNumDevices() {return numDevices;}
	public int getNumDevicesOffOk() {return numDevicesOffOk;}
	public double getTstep() {return tstep;}
	public double getMachineMTTF() {return machineMTTF;}
	public double getMachineMTTR() {return machineMTTR;}
	public double getMachineAvail() {return machineAvail;}

	public void setNumFailures(int numFailures) {this.numFailures = numFailures;}
	public void setDevMTTF(double devMTTF) {this.devMTTF = devMTTF; initializeDevices();}
	public void setDevMTTR(double devMTTR) {this.devMTTR = devMTTR; initializeDevices();}
	public void setNumDevices(int numDevices) {this.numDevices = numDevices; initializeDevices();}
	public void setNumDevicesOffOk(int numDevicesOffOk) {this.numDevicesOffOk = numDevicesOffOk;}
	public void setTstep(double tstep) {this.tstep = tstep; initializeDevices();}
	
	public static void main(String[] args) throws Exception 
	{
		int numFailures = 10000;
		double devMTTF = 40.0;
		double devMTTR = 1.0;
		int numDevices = 146;
		int numDevicesOffOk  = 0;
		double tstep = devMTTR * .01;
		DownTimeSimulator ds  = new DownTimeSimulator(numFailures, devMTTF, devMTTR, numDevices, numDevicesOffOk, tstep);
		ds.generateDistribution();
		System.out.println("Machine MTTF = " + ds.getMachineMTTF());
		System.out.println("Machine MTTR = " + ds.getMachineMTTR());
		System.out.println("Machine Avail = " + ds.getMachineAvail());
	}

}
